package com.cskaoyan.gateway.controller.promo;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cskaoyan.gateway.cache.CacheManager;
import com.cskaoyan.gateway.form.promo.CreatePromoOrderInfo;
import com.google.common.util.concurrent.RateLimiter;
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.promo.PromoService;
import com.mall.promo.dto.*;
import com.mall.user.annotation.Anoymous;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.intercepter.TokenIntercepter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.*;

@RestController
@RequestMapping("/shopping")
@Slf4j
public class PromoController {

    @Reference(check = false, timeout = 3000)
    PromoService promoService;


    @Autowired
    CacheManager cacheManager;


    RateLimiter rateLimiter;


    ExecutorService executorService;


    @PostConstruct
    public void init() {
        // 创建令牌桶
        // 这里的参数100指定的是，令牌桶每秒产生的令牌个数
        rateLimiter = RateLimiter.create(100);

        executorService = Executors.newFixedThreadPool(100);
    }


    @GetMapping("/seckilllist")
    @Anoymous
    public ResponseData getPromotionList(@RequestParam Integer sessionId) {
        PromoInfoRequest promoInfoRequest = new PromoInfoRequest();
        promoInfoRequest.setSessionId(sessionId);

        String yyyyMMdd = DateFormatUtils.format(new Date(), "yyyyMMdd");
        promoInfoRequest.setYyyymmdd(yyyyMMdd);
        PromoInfoResponse promoInfoResponse = promoService.getPromoList(promoInfoRequest);
        if (!promoInfoResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())) {
            return new ResponseUtil<>().setErrorMsg(promoInfoResponse.getMsg());
        }
        return new ResponseUtil<>().setData(promoInfoResponse);

    }


    @PostMapping("/promoProductDetail")
    public ResponseData getPromoItemDetail(@RequestBody PromoProductDetailRequest request) {

        PromoProductDetailResponse response = promoService.getPromoProductDetail(request);
        if (!response.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())) {
            return new ResponseUtil<>().setErrorMsg(response.getMsg());
        }
        return new ResponseUtil<>().setData(response);
    }


    @PostMapping("/seckill")
    public ResponseData seckill(HttpServletRequest request,
                                @RequestBody CreatePromoOrderInfo createPromoOrderInfo) {

        CreatePromoOrderResponse createPromoOrderResponse = null;


        //  使用令牌桶
        // 获取一个令牌, 如果获取令牌成功，代码就正常执行，否则，获取令牌失败，就会阻塞等待一端时间
        rateLimiter.acquire();

        //  业务限流
        // 首先判断，秒杀商品是否已经售罄，如果售罄，直接返回秒杀失败
        Long productId = createPromoOrderInfo.getProductId();
        Long psId = createPromoOrderInfo.getPsId();

        String key = "promo_stock_not_enough: " + psId + "-" + productId;
        String result = cacheManager.checkCache(key);
        if (result != null && "yes".equals(result.trim())) {
            // 返回秒杀失败的响应
            return new ResponseUtil<>().setErrorMsg("秒杀商品已售罄");
        }

        String userInfo = (String) request.getAttribute(TokenIntercepter.USER_INFO_KEY);
        JSONObject jsonObject = JSON.parseObject(userInfo);
        String username = (String) jsonObject.get("username");
        Integer uid = (Integer) jsonObject.get("id");

        // 初始化 createPromoOrderRequest
        CreatePromoOrderRequest createPromoOrderRequest = getCreatePromoOrderRequest(createPromoOrderInfo, username, uid);


        Future<CreatePromoOrderResponse> asyncResult = executorService.submit(new Callable<CreatePromoOrderResponse>() {
            @Override
            public CreatePromoOrderResponse call() throws Exception {
                return promoService.createPromoOrderInTransaction(createPromoOrderRequest);
            }
        });

        // 获取线程池中，执行的结果
        try {
            createPromoOrderResponse = asyncResult.get();
        } catch (Exception e) {
            e.printStackTrace();
            // 返回秒杀失败的响应
            return new ResponseUtil<>().setErrorMsg("秒杀失败");
        }


        log.info("promo controller submit.get return " + createPromoOrderResponse.getCode());
        if (!createPromoOrderResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())) {
            return new ResponseUtil<>().setErrorMsg(createPromoOrderResponse.getMsg());
        }
        return new ResponseUtil<>().setData(createPromoOrderResponse);
    }


    /**
     * 初始化createPromoOrderRequest
     *
     * @param createPromoOrderInfo
     * @param username
     * @param uid
     * @return
     */
    private CreatePromoOrderRequest getCreatePromoOrderRequest(@RequestBody CreatePromoOrderInfo createPromoOrderInfo, String username, Integer uid) {

        CreatePromoOrderRequest createPromoOrderRequest = new CreatePromoOrderRequest();
        createPromoOrderRequest.setProductId(createPromoOrderInfo.getProductId());
        createPromoOrderRequest.setPsId(createPromoOrderInfo.getPsId());
        createPromoOrderRequest.setUserId(uid.longValue());
        createPromoOrderRequest.setUsername(username);

        //增加地址信息
        createPromoOrderRequest.setAddressId(createPromoOrderInfo.getAddressId());
        createPromoOrderRequest.setStreetName(createPromoOrderInfo.getStreetName());
        createPromoOrderRequest.setTel(createPromoOrderInfo.getTel());
        return createPromoOrderRequest;
    }


}
